/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.lightswitch.smarttranslator.processing;

import com.lightswitch.smarttranslator.translator.TranslatorHelper;
import com.lightswitch.smarttranslator.webservice.__OCRMode;
import com.lightswitch.smarttranslator.webservice.__TranslateResponsingModel;
import java.awt.image.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import net.sourceforge.tess4j.*;

/**
 *
 * @author HieuPham
 */
public class SmartTranslatorProcessor {

    protected static Map processorMap = new HashMap();

    protected static SmartTranslatorProcessor getProcessor(String lOrigin, String lResult) {
        return (SmartTranslatorProcessor) processorMap.get(lOrigin + lResult);
    }

    public static SmartTranslatorProcessor getInstanceOrInitProcessor(String lOrigin, String lResult) {
        String key = lOrigin + lResult;

        if (!processorMap.containsKey(key)) {
            initNewProcessor(lOrigin, lResult);
        }

        return getProcessor(lOrigin, lResult);
    }

    protected static void initNewProcessor(String lOrigin, String lResult) {
        String key = lOrigin + lResult;

        SmartTranslatorProcessor newProcessor = new SmartTranslatorProcessor(lOrigin, lResult);
        processorMap.put(key, newProcessor);
    }
    protected String langOrigin = "eng"; // set default
    protected String langResult = "vie"; // set default

    protected SmartTranslatorProcessor(String lOrigin, String lResult) {
        langOrigin = lOrigin;
        langResult = lResult;
    }

    public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(obj);
        return b.toByteArray();
    }

    public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream b = new ByteArrayInputStream(bytes);
        ObjectInputStream o = new ObjectInputStream(b);
        return o.readObject();
    }

    public __TranslateResponsingModel process(List<Byte> _imageBytes, __OCRMode _ocrMode) throws IOException, TesseractException {
        byte[] bytes = serialize(_imageBytes);
        BufferedImage originImage = createImageFromBytes(bytes);
        switch (_ocrMode) {
            case _DETECT_ONLY:
                return detectOnly(originImage);
            case _DETECT_AND_TRANSLATE:
                return detectAndTranslate(originImage);
            case _DETECT_TRANSLATE_AND_REPAINT:
                return detectTranslateAndRepaint(originImage);
            default:
                return null;
        }
    }

    private BufferedImage createImageFromBytes(byte[] imageData) {
        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
        try {
            return ImageIO.read(bais);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private List<Byte> createBytesFromBufferdImage(BufferedImage image) {
        WritableRaster raster = image.getRaster();
        DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
        byte[] bytes = data.getData();
        List<Byte> result = new ArrayList<>();
        for (int i = 0; i < bytes.length; i++) {
            result.add(new Byte(bytes[i]));
        }
        return result;
    }

    private __TranslateResponsingModel detectOnly(BufferedImage originImage) throws TesseractException {
        Tesseract tesseract = Tesseract.getInstance();
        tesseract.setLanguage(langOrigin);

        String recognizedText = tesseract.doOCR(originImage);
        List<Byte> bytes = createBytesFromBufferdImage(originImage);
        return new __TranslateResponsingModel(bytes, recognizedText, recognizedText, null);
    }

    private __TranslateResponsingModel detectAndTranslate(BufferedImage originImage) throws TesseractException {

        String langOrigin = "eng";
        Tesseract tesseract = Tesseract.getInstance();
        tesseract.setLanguage(langOrigin);
        String recognizedText = tesseract.doOCR(originImage);//"Hello, teacher! I'm Linda";
        List<Byte> bytes = createBytesFromBufferdImage(originImage);
        String translateText = TranslatorHelper.TranslateWithDefaultLanguage(recognizedText);
        return new __TranslateResponsingModel(bytes, recognizedText, translateText, null);


    }

    private __TranslateResponsingModel detectTranslateAndRepaint(BufferedImage originImage) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
